﻿using System.Collections.Generic;
using System.Xml;

namespace Jayden.Dll.Core
{
	public class Configuration
	{
		private Configuration m_Parent;
		private string m_SaveFilepath;
		private XmlElement m_Root;

		public Configuration(string filepath)
		{
			m_Parent = null;
			m_SaveFilepath = filepath;
			XmlDocument document = new XmlDocument();
			document.Load(filepath);
			m_Root = document.DocumentElement;
		}
		public Configuration(XmlDocument document)
		{
			m_Parent = null;
			m_SaveFilepath = null;
			m_Root = document.DocumentElement;
		}
		public Configuration(Configuration parent, XmlElement element)
		{
			m_Parent = parent;
			m_SaveFilepath = null;
			m_Root = element;
		}

		public string GetValue(string xpath, string defaultValue = null)
		{
			XmlNode node = m_Root.SelectSingleNode(xpath);
			if (node == null)
				return defaultValue;
			if (node is XmlElement)
				return node.InnerText;
			return node.Value;
		}
		public string[] GetValues(string xpath)
		{
			XmlNodeList nodes = m_Root.SelectNodes(xpath);
			if (nodes == null || nodes.Count == 0)
				return new string[0];
			List<string> values = new List<string>();
			foreach (XmlNode node in nodes)
			{
				if (node is XmlElement)
					values.Add(node.InnerText);
				values.Add(node.Value);
			}
			return values.ToArray();
		}
		public Dictionary<string, string> GetDictionary(string xpathKeys, string xpathValues)
		{
			string[] keys = GetValues(xpathKeys);
			string[] values = GetValues(xpathValues);
			if (keys == null || values == null || keys.Length != values.Length)
				return null;
			Dictionary<string, string> dico = new Dictionary<string, string>();
			for (int c = 0; c < keys.Length; c++)
				dico.Add(keys[c], values[c]);
			return dico;
		}

		public Configuration GetConfiguration(string xpath)
		{
			XmlElement root = m_Root.SelectSingleNode(xpath) as XmlElement;
			if (root == null)
				return null;
			return new Configuration(this, root);
		}

		public IEnumerable<Configuration> GetConfigurations(string xpath)
		{
			XmlNodeList nodes = m_Root.SelectNodes(xpath);
			if (nodes == null || nodes.Count == 0)
				yield break;
			foreach (XmlNode node in nodes)
			{
				if(node is XmlElement)
					yield return new Configuration(this, node as XmlElement);
			}
		}

		public void Save()
		{
			Configuration current = this;
			while (current != null)
			{
				if(current.m_SaveFilepath != null)
					current.m_Root.OwnerDocument.Save(current.m_SaveFilepath);
				current = current.m_Parent;
			}
		}
	}
}
